home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / ghostview / callbacks.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  21KB  |  729 lines

  1. /*
  2.  * callbacks.c -- X11 callbacks for ghostview.
  3.  * Copyright (C) 1992  Timothy O. Theisen
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  *   Author: Tim Theisen           Systems Programmer
  20.  * Internet: tim@cs.wisc.edu       Department of Computer Sciences
  21.  *     UUCP: uwvax!tim             University of Wisconsin-Madison
  22.  *    Phone: (608)262-0438         1210 West Dayton Street
  23.  *      FAX: (608)262-9777         Madison, WI   53706
  24.  */
  25.  
  26. #include <stdio.h>
  27. #ifndef BUFSIZ
  28. #define BUFSIZ 1024
  29. #endif
  30.  
  31. #ifdef VMS
  32. #define getenv _getenv
  33. #endif
  34.  
  35. extern char *getenv();
  36.  
  37. #include <X11/Intrinsic.h>
  38. #include <X11/StringDefs.h>
  39. #include <X11/Shell.h>
  40. #include <X11/Xaw/Cardinals.h>
  41. #include <X11/Xaw/AsciiText.h>
  42. #include <X11/Xaw/Scrollbar.h>
  43. #include <X11/Xaw/Form.h>
  44. #include <X11/Xaw/Command.h>
  45.  
  46. #include "Ghostview.h"
  47. #include "gv.h"
  48. #include "ps.h"
  49.  
  50. /* Start application folding up by Destroying the top level widget. */
  51. /* The application exits when the last interpreter is killed during */
  52. /* a destroy callback from ghostview widgets. */
  53. void
  54. quit_ghostview(w, client_data, call_data)
  55.     Widget w;
  56.     XtPointer client_data, call_data;
  57. {
  58.     XtDestroyWidget(toplevel);
  59. }
  60.  
  61. /* Popup a window. */
  62. void
  63. popup(w, client_data, call_data)
  64.     Widget w;
  65.     XtPointer client_data, call_data;
  66. {
  67.     positionpopup((Widget)client_data);
  68.     XtPopup((Widget)client_data, XtGrabNone);
  69.     XRaiseWindow(XtDisplay((Widget)client_data), XtWindow((Widget)client_data));
  70. }
  71.  
  72. /* Popup a dialog box. */
  73. void
  74. popup_dialog(w, client_data, call_data)
  75.     Widget w;
  76.     XtPointer client_data, call_data;
  77. {
  78. #ifdef SELFILE
  79.     Widget button;
  80.     String okay, cancel;
  81.     String name, init_path;
  82.     Arg args[1];
  83.     FILE* fp;
  84.     struct stat sbuf;
  85.     extern FILE *XsraSelFile();
  86.  
  87.     button = XtNameToWidget(dialog, "cancel");
  88.     if (button) {
  89.     XtSetArg(args[0], XtNlabel, &cancel);
  90.     XtGetValues(button, args, ONE);
  91.     }
  92.     button = XtNameToWidget(dialog, "okay");
  93.     if (button) {
  94.     XtSetArg(args[0], XtNlabel, &okay);
  95.     XtGetValues(button, args, ONE);
  96.     }
  97. #endif
  98.  
  99.     mode = (int) client_data;
  100.     switch (mode) {
  101.     case PRINT_WHOLE:
  102.     case PRINT_MARKED:
  103.     SetDialogPrompt(dialog, app_res.print_prompt);
  104.     if (app_res.default_printer)
  105.         SetDialogResponse(dialog, app_res.default_printer);
  106.     else
  107.         ClearDialogResponse(dialog);
  108.     popup(w, (XtPointer)dialogpopup, call_data);
  109.     break;
  110.     case OPEN:
  111. #ifdef SELFILE
  112.     if (filename && strcmp(filename, "-")) init_path = filename;
  113.     else init_path = NULL;
  114.     fp = XsraSelFile(toplevel, app_res.open_prompt, okay, cancel,
  115.              app_res.open_fail, init_path, "r", NULL, &name);
  116.     if (fp == NULL) break;
  117.     if (oldfilename) XtFree(oldfilename);
  118.     oldfilename = filename;
  119.     filename = name;
  120.     if (psfile) fclose(psfile);
  121.     psfile = fp;
  122.     stat(filename, &sbuf);
  123.     mtime = sbuf.st_mtime;
  124.     new_file(0);
  125.     show_page(0);
  126. #else
  127.     SetDialogPrompt(dialog, app_res.open_prompt);
  128.     if (filename && strcmp(filename, "-"))
  129.         SetDialogResponse(dialog, filename);
  130.     else
  131.         ClearDialogResponse(dialog);
  132.     popup(w, dialogpopup, call_data);
  133. #endif
  134.     break;
  135.     case SAVE:
  136. #ifdef SELFILE
  137.     fp = XsraSelFile(toplevel, app_res.save_prompt, okay, cancel,
  138.              app_res.save_fail, "", "w", NULL, &name);
  139.     if (fp == NULL) break;
  140.     pscopydoc(fp);
  141.     fclose(fp);
  142.     XtFree(name);
  143. #else
  144.     SetDialogPrompt(dialog, app_res.save_prompt);
  145.     ClearDialogResponse(dialog);
  146.     popup(w, dialogpopup, call_data);
  147. #endif
  148.     break;
  149.     }
  150. }
  151.  
  152. /* Explicitly reopen the file. */
  153. void
  154. reopen_file(w, client_data, call_data)
  155.     Widget w;
  156.     XtPointer client_data, call_data;
  157. {
  158.     struct stat sbuf;
  159.     int number = current_page;
  160.  
  161.     fclose(psfile);
  162.     psfile = fopen(filename, "r");
  163.     mtime = sbuf.st_mtime;
  164.     if (oldfilename) XtFree(oldfilename);
  165.     oldfilename = XtNewString(filename);
  166.     new_file(number);
  167.     show_page(number);
  168. }
  169.  
  170. /* Get the selection, if no selection, get the insertion point. */
  171. /* If the new_page is different from the current page show it.  */
  172. /* If not at the first page, show the previous page. */
  173. void
  174. prev_page(w, client_data, call_data)
  175.     Widget w;
  176.     XtPointer client_data, call_data;
  177. {
  178.     XawTextPosition pos, end;
  179.     int new_page;
  180.  
  181.     XawTextGetSelectionPos(toc, &pos, &end);
  182.     if (pos == end) {        /* Nothing selected */
  183.     pos = XawTextGetInsertionPoint(toc);
  184.     }
  185.     if ((new_page = pos/toc_entry_length) == current_page) {
  186.     new_page = current_page - 1;
  187.     }
  188.     if (new_page < 0) return;
  189.     show_page(new_page);
  190. }
  191.  
  192. /* Get the selection, if no selection, get the insertion point. */
  193. /* Show this page.  */
  194. void
  195. this_page(w, client_data, call_data)
  196.     Widget w;
  197.     XtPointer client_data, call_data;
  198. {
  199.     if (toc_text) {
  200.     XawTextPosition pos, end;
  201.     int new_page;
  202.  
  203.     XawTextGetSelectionPos(toc, &pos, &end);
  204.     if (pos == end) {        /* Nothing selected */
  205.         pos = XawTextGetInsertionPoint(toc);
  206.     }
  207.     new_page = pos/toc_entry_length;
  208.     show_page(new_page);
  209.     } else {
  210.     GhostviewDisableInterpreter(page);
  211.     show_page(0);
  212.     }
  213. }
  214.  
  215. /* Get the selection, if no selection, get the insertion point. */
  216. /* If the new_page is different from the current page show it.  */
  217. /* If not at the last page, show the next page. */
  218. void
  219. next_page(w, client_data, call_data)
  220.     Widget w;
  221.     XtPointer client_data, call_data;
  222. {
  223.     XawTextPosition pos, end;
  224.     int new_page = 0;
  225.  
  226.     if (toc_text) {
  227.     XawTextGetSelectionPos(toc, &pos, &end);
  228.     if (pos == end) {        /* Nothing selected */
  229.         pos = XawTextGetInsertionPoint(toc);
  230.     }
  231.     if ((new_page = pos/toc_entry_length) == current_page) {
  232.         new_page = current_page + 1;
  233.     }
  234.     if (new_page >= doc->numpages) return;
  235.     }
  236.     show_page(new_page);
  237. }
  238.  
  239. /* Center the viewport over the page */
  240. void
  241. center_page(w, client_data, call_data)
  242.     Widget w;
  243.     XtPointer client_data, call_data;
  244. {
  245.     Arg args[2];
  246.     Widget scroll;
  247.     float top, shown;
  248.  
  249.     scroll = XtNameToWidget(pageview, "vertical");
  250.     if (scroll) {
  251.     XtSetArg(args[0], XtNshown, &shown);
  252.     XtSetArg(args[1], XtNtopOfThumb, &top);
  253.     XtGetValues(scroll, args, TWO);
  254.  
  255.     top = (1.0 - shown) / 2.0;
  256.     XtCallCallbacks(scroll, XtNjumpProc, &top);
  257.     }
  258.  
  259.     scroll = XtNameToWidget(pageview, "horizontal");
  260.     if (scroll) {
  261.     XtSetArg(args[0], XtNshown, &shown);
  262.     XtSetArg(args[1], XtNtopOfThumb, &top);
  263.     XtGetValues(scroll, args, TWO);
  264.  
  265.     top = (1.0 - shown) / 2.0;
  266.     XtCallCallbacks(scroll, XtNjumpProc, &top);
  267.     }
  268. }
  269.  
  270. /* Get the selection, if no selection, get the insertion point. */
  271. /* Mark all pages in range, and cause toc to update. */
  272. void
  273. mark_page(w, client_data, call_data)
  274.     Widget w;
  275.     XtPointer client_data, call_data;
  276. {
  277.     XawTextPosition begin, end;
  278.     int i;
  279.  
  280.     XawTextGetSelectionPos(toc, &begin, &end);
  281.     if (begin == end) {        /* Nothing selected */
  282.     begin = end = XawTextGetInsertionPoint(toc);
  283.     } else {
  284.     end--;            /* Sometimes end spills onto next line */
  285.     }
  286.     for (i = begin/toc_entry_length; i <= end/toc_entry_length; i++) {
  287.     toc_text[i*toc_entry_length] = '*';
  288.     XawTextInvalidate(toc, i*toc_entry_length, i*toc_entry_length+1);
  289.     }
  290. }
  291.  
  292. /* Get the selection, if no selection, get the insertion point. */
  293. /* Unmark all pages in range, and cause toc to update. */
  294. void
  295. unmark_page(w, client_data, call_data)
  296.     Widget w;
  297.     XtPointer client_data, call_data;
  298. {
  299.     XawTextPosition begin, end;
  300.     int i;
  301.  
  302.     XawTextGetSelectionPos(toc, &begin, &end);
  303.     if (begin == end) {        /* Nothing selected */
  304.     begin = end = XawTextGetInsertionPoint(toc);
  305.     } else {
  306.     end--;            /* Sometimes end spills onto next line */
  307.     }
  308.     for (i = begin/toc_entry_length; i <= end/toc_entry_length; i++) {
  309.     toc_text[i*toc_entry_length] = ' ';
  310.     XawTextInvalidate(toc, i*toc_entry_length, i*toc_entry_length+1);
  311.     }
  312. }
  313.  
  314. /* Set new magstep.  Reshow the current page if magstep changed. */
  315. void
  316. set_magstep(w, client_data, call_data)
  317.     Widget w;
  318.     XtPointer client_data, call_data;
  319. {
  320.     app_res.magstep = (int)client_data;
  321.     if (set_new_magstep()) {
  322.     layout_ghostview();
  323.     show_page(current_page);
  324.     }
  325. }
  326.  
  327. /* Set new orientation.  Reshow the current page if orientation changed. */
  328. void
  329. set_orientation(w, client_data, call_data)
  330.     Widget w;
  331.     XtPointer client_data, call_data;
  332. {
  333.     app_res.force_orientation = force_setting;
  334.     app_res.orientation = (XtPageOrientation) client_data;
  335.     if (set_new_orientation(current_page)) {
  336.     layout_ghostview();
  337.     show_page(current_page);
  338.     }
  339. }
  340.  
  341. /* Swap the landscape labels and change the flag. */
  342. void
  343. swap_landscape(w, client_data, call_data)
  344.     Widget w;
  345.     XtPointer client_data, call_data;
  346. {
  347.     Arg args[1];
  348.     String s1, s2;
  349.  
  350.     app_res.swap_landscape = !app_res.swap_landscape;
  351.  
  352.     XtSetArg(args[0], XtNlabel, &s1);
  353.     XtGetValues(landscapebutton, args, ONE);
  354.     s1 = XtNewString(s1);
  355.     XtSetArg(args[0], XtNlabel, &s2);
  356.     XtGetValues(seascapebutton, args, ONE);
  357.     s2 = XtNewString(s2);
  358.     XtSetArg(args[0], XtNlabel, s2);
  359.     XtSetValues(landscapebutton, args, ONE);
  360.     XtSetArg(args[0], XtNlabel, s1);
  361.     XtSetValues(seascapebutton, args, ONE);
  362.     XtFree(s1);
  363.     XtFree(s2);
  364.  
  365.     if (set_new_orientation(current_page)) {
  366.     layout_ghostview();
  367.     show_page(current_page);
  368.     }
  369. }
  370.  
  371. /* Set new page media.  If new page media is different, update app_resources */
  372. /* and redisplay page. */
  373. void
  374. set_pagemedia(w, client_data, call_data)
  375.     Widget w;
  376.     XtPointer client_data, call_data;
  377. {
  378.     int new_pagemedia = (int) client_data;
  379.     if (new_pagemedia >= base_papersize) {
  380.     default_pagemedia = new_pagemedia;
  381.     app_res.force_pagemedia = force_setting;
  382.     } else {
  383.     document_media = new_pagemedia;
  384.     force_document_media = force_setting;
  385.     }
  386.     if (set_new_pagemedia(current_page)) {
  387.     layout_ghostview();
  388.     show_page(current_page);
  389.     }
  390. }
  391.  
  392. /* track mouse pointer and popup zoom window */
  393. void
  394. track_and_zoom(w, client_data, call_data)
  395.     Widget w;
  396.     XtPointer client_data, call_data;
  397. {
  398.     Arg args[20];
  399.     Cardinal num_args;
  400.     Dimension width, height;
  401.     Widget zoom;
  402.     Widget zoomform;
  403.     Widget zoompage;
  404.     Widget zoomdismiss;
  405.     FILE *zoomfile;
  406.     struct stat sbuf;
  407.     GhostviewReturnStruct *p = (GhostviewReturnStruct *)call_data;
  408.     int llx;
  409.     int lly;
  410.     int urx;
  411.     int ury;
  412.     int bottom_margin;
  413.     int left_margin;
  414.     int right_margin;
  415.     int top_margin;
  416.     int i;
  417.  
  418.     /* locator events have zero width and height */
  419.     if ((p->width == 0) || (p->height == 0)) {
  420.     char buf[32];
  421.     if (!app_res.show_locator) return;
  422.     sprintf(buf, "(%d, %d)", p->psx, p->psy);
  423.     XtSetArg(args[0], XtNlabel, buf);
  424.     XtSetValues(locator, args, ONE);
  425.     return;
  426.     }
  427.  
  428.     /* If no file, nothing to zoom. */
  429.     if (!psfile) return;
  430.  
  431.     /* If the file changed, cannot zoom */
  432.     stat(filename, &sbuf);
  433.     if (mtime != sbuf.st_mtime) return;
  434.                             num_args = 0;
  435.     XtSetArg(args[num_args], XtNcolormap, cmap);    num_args++;
  436.     if (special_cmap) {
  437.     XtSetArg(args[num_args], XtNbackground, white);    num_args++;
  438.     }
  439.     zoom = XtCreatePopupShell("zoom", topLevelShellWidgetClass,
  440.                   toplevel, args, num_args);
  441.  
  442.                             num_args = 0;
  443.     if (special_cmap) {
  444.     XtSetArg(args[num_args], XtNbackground, white);    num_args++;
  445.     }
  446.     zoomform = XtCreateManagedWidget("form", formWidgetClass,
  447.                      zoom, args, num_args);
  448.  
  449.     llx = p->psx - p->width/2;
  450.     lly = p->psy - p->height/2;
  451.     urx = p->psx + p->width/2;
  452.     ury = p->psy + p->height/2;
  453.  
  454.     /* Make sure zoom window doesn't go off the edge of the page */
  455.     if (llx < current_llx) {
  456.     llx = current_llx;
  457.     urx = llx + p->width;
  458.     }
  459.     if (lly < current_lly) {
  460.     lly = current_lly;
  461.     ury = lly + p->height;
  462.     }
  463.     if (urx > current_urx) {
  464.     urx = current_urx;
  465.     llx = urx - p->width;
  466.     }
  467.     if (ury > current_ury) {
  468.     ury = current_ury;
  469.     lly = ury - p->height;
  470.     }
  471.     if (llx < current_llx) {
  472.     llx = current_llx;
  473.     }
  474.     if (lly < current_lly) {
  475.     lly = current_lly;
  476.     }
  477.     bottom_margin = lly - current_lly;
  478.     left_margin = llx - current_llx;
  479.     right_margin = current_urx - urx;
  480.     top_margin = current_ury - ury;
  481.  
  482.                             num_args = 0;
  483.     if (special_cmap) {
  484.     XtSetArg(args[num_args], XtNbackground, white);    num_args++;
  485.     }
  486.     XtSetArg(args[num_args], XtNtop, XtChainTop);    num_args++;
  487.     XtSetArg(args[num_args], XtNbottom, XtChainBottom);    num_args++;
  488.     XtSetArg(args[num_args], XtNleft, XtChainLeft);    num_args++;
  489.     XtSetArg(args[num_args], XtNright, XtChainRight);    num_args++;
  490.     XtSetArg(args[num_args], XtNorientation, current_orientation);
  491.                             num_args++;
  492.     XtSetArg(args[num_args], XtNllx, llx);          num_args++;
  493.     XtSetArg(args[num_args], XtNlly, lly);          num_args++;
  494.     XtSetArg(args[num_args], XtNurx, urx);          num_args++;
  495.     XtSetArg(args[num_args], XtNury, ury);          num_args++;
  496.     XtSetArg(args[num_args], XtNbottomMargin, bottom_margin);
  497.                             num_args++;
  498.     XtSetArg(args[num_args], XtNleftMargin, left_margin);
  499.                             num_args++;
  500.     XtSetArg(args[num_args], XtNrightMargin, right_margin);
  501.                             num_args++;
  502.     XtSetArg(args[num_args], XtNtopMargin, top_margin); num_args++;
  503.     XtSetArg(args[num_args], XtNbottomMargin, bottom_margin);
  504.                             num_args++;
  505.     XtSetFloatArg(args[num_args], XtNxdpi, p->xdpi);    num_args++;
  506.     XtSetFloatArg(args[num_args], XtNydpi, p->ydpi);    num_args++;
  507.     if (!toc_text) {
  508.         XtSetArg(args[num_args], XtNfilename, filename);    num_args++;
  509.     }
  510.     zoompage = XtCreateManagedWidget("page", ghostviewWidgetClass,
  511.                      zoomform, args, num_args);
  512.     num_ghosts++;
  513.     XtAddCallback(zoompage, XtNcallback, track_and_zoom, (XtPointer)0);
  514.     XtAddCallback(zoompage, XtNmessageCallback, message, (XtPointer)zoompage);
  515.     XtAddCallback(zoompage, XtNdestroyCallback, destroy_ghost,
  516.           (XtPointer)zoompage);
  517.  
  518.                             num_args = 0;
  519.     if (special_cmap) {
  520.     XtSetArg(args[num_args], XtNforeground, black);    num_args++;
  521.     XtSetArg(args[num_args], XtNbackground, white);    num_args++;
  522.     }
  523.     XtSetArg(args[num_args], XtNfromVert, zoompage);    num_args++;
  524.     XtSetArg(args[num_args], XtNtop, XtChainBottom);    num_args++;
  525.     XtSetArg(args[num_args], XtNbottom, XtChainBottom);    num_args++;
  526.     XtSetArg(args[num_args], XtNleft, XtChainLeft);    num_args++;
  527.     XtSetArg(args[num_args], XtNright, XtChainRight);    num_args++;
  528.     zoomdismiss = XtCreateManagedWidget("dismiss", commandWidgetClass,
  529.                        zoomform, args, num_args);
  530.     XtAddCallback(zoomdismiss, XtNcallback, destroy, (XtPointer)zoom);
  531.  
  532.     XtSetArg(args[0], XtNwidth, &width);
  533.     XtGetValues(zoompage, args, ONE);
  534.     XtSetArg(args[0], XtNwidth, width);
  535.     XtSetValues(zoomdismiss, args, ONE);
  536.  
  537.     XtRealizeWidget(zoom);
  538.     positionpopup(zoom);
  539.  
  540.                             num_args = 0;
  541.     XtSetArg(args[num_args], XtNwidth, &width);        num_args++;
  542.     XtSetArg(args[num_args], XtNheight, &height);    num_args++;
  543.     XtGetValues(zoom, args, num_args);
  544.  
  545.                                       num_args = 0;
  546.     XtSetArg(args[num_args], XtNminWidth, width);        num_args++;
  547.     XtSetArg(args[num_args], XtNminHeight, height);        num_args++;
  548.     XtSetArg(args[num_args], XtNmaxWidth, width);        num_args++;
  549.     XtSetArg(args[num_args], XtNmaxHeight, height);        num_args++;
  550.     XtSetValues(zoom, args, num_args);
  551.     XSetWMProtocols(XtDisplay(zoom), XtWindow(zoom), &wm_delete_window, 1);
  552.     XtPopup(zoom, XtGrabNone);
  553.  
  554.     if (toc_text) {
  555.     zoomfile = fopen(filename, "r");
  556.     if (zoomfile == NULL) return;
  557.     GhostviewSendPS(zoompage, zoomfile, doc->beginprolog,
  558.             doc->lenprolog, False);
  559.     GhostviewSendPS(zoompage, zoomfile, doc->beginsetup,
  560.             doc->lensetup, False);
  561.     if (doc->pageorder == DESCEND)
  562.         i = (doc->numpages - 1) - current_page;
  563.     else
  564.         i = current_page;
  565.     GhostviewSendPS(zoompage, zoomfile, doc->pages[i].begin,
  566.             doc->pages[i].len, True);
  567.     }
  568. }
  569.  
  570. /* Process messages from ghostscript */
  571. /* Refresh occurs when window was resized unexpectedly */
  572. void
  573. message(w, client_data, call_data)
  574.     Widget w;
  575.     XtPointer client_data, call_data;
  576. {
  577.     int i;
  578.     char *error;
  579.  
  580.     if (!strcmp((char *) call_data, "Failed")) {
  581.     if ((Widget)client_data == page) {
  582.         error = "Error: PostScript interpreter failed in main window.\n\n";
  583.     } else {
  584.         error = "Error: PostScript interpreter failed in zoom window.\n\n";
  585.     }
  586.     output(w, NULL, error);
  587.     } else if (!strcmp((char *) call_data, "BadAlloc")) {
  588.     if ((Widget)client_data == page) {
  589.         error = 
  590.            "Warning: Could not allocate backing pixmap in main window.\n\n";
  591.     } else {
  592.         error = 
  593.            "Warning: Could not allocate backing pixmap in zoom window.\n\n";
  594.     }
  595.     output(w, NULL, error);
  596.     } else if (!strcmp((char *) call_data, "Refresh")) {
  597.     if (toc_text) {
  598.         GhostviewSendPS(w, psfile, doc->beginprolog,
  599.                 doc->lenprolog, False);
  600.         GhostviewSendPS(w, psfile, doc->beginsetup,
  601.                 doc->lensetup, False);
  602.         if (doc->pageorder == DESCEND)
  603.         i = (doc->numpages - 1) - current_page;
  604.         else
  605.         i = current_page;
  606.         GhostviewSendPS(w, psfile, doc->pages[i].begin,
  607.                 doc->pages[i].len, False);
  608.     }
  609.     }
  610. }
  611.  
  612. /* Take output from ghostscript and display it in the infotext popup window */
  613. void
  614. output(w, client_data, call_data)
  615.     Widget w;
  616.     XtPointer client_data, call_data;
  617. {
  618.     Arg args[2];
  619.     XawTextBlock message_block;
  620.  
  621.     message_block.firstPos = 0;
  622.     message_block.length = strlen(call_data);
  623.     message_block.ptr = call_data;
  624.     message_block.format = FMT8BIT;
  625.  
  626.     XawTextDisableRedisplay(infotext);
  627.  
  628.     XtSetArg(args[0], XtNeditType, XawtextAppend);
  629.     XtSetValues(infotext, args, ONE);
  630.     XawTextReplace(infotext, info_length, info_length, &message_block);
  631.     info_length = info_length + message_block.length;
  632.  
  633.     XtSetArg(args[0], XtNeditType, XawtextRead);
  634.     XtSetArg(args[1], XtNinsertPosition, info_length);
  635.     XtSetValues(infotext, args, TWO);
  636.     XawTextEnableRedisplay(infotext);
  637.     if (!info_up) XtPopup(infopopup, XtGrabNone);
  638.     info_up = True;
  639. }
  640.  
  641. /* Dismiss popup dialog */
  642. void
  643. okay(w, client_data, call_data)
  644.     Widget w;
  645.     XtPointer client_data, call_data;
  646. {
  647.     String name, error;
  648.     Widget dialog;
  649.  
  650.     dialog = (Widget)client_data;
  651.     name = GetDialogResponse(dialog);
  652.     switch (mode) {
  653.     case PRINT_WHOLE:
  654.     case PRINT_MARKED:
  655.     if (error = print_file(name, (mode == PRINT_WHOLE))) {
  656.         char *buf = XtMalloc(strlen(error) +
  657.                  strlen(app_res.print_prompt) + 2);
  658.         sprintf(buf, "%s\n%s", error, app_res.print_prompt);
  659.         SetDialogPrompt(dialog, buf);
  660.         XtFree(error);
  661.         XtFree(buf);
  662.     } else {
  663.         XtPopdown(XtParent(dialog));
  664.     }
  665.     break;
  666.     case OPEN:
  667.     if (error = open_file(name)) {
  668.         char *buf = XtMalloc(strlen(error) +
  669.                  strlen(app_res.open_prompt) + 2);
  670.         sprintf(buf, "%s\n%s", error, app_res.open_prompt);
  671.         SetDialogPrompt(dialog, buf);
  672.         XtFree(error);
  673.         XtFree(buf);
  674.     } else {
  675.         XtPopdown(XtParent(dialog));
  676.     }
  677.     break;
  678.     case SAVE:
  679.     if (error = save_file(name)) {
  680.         char *buf = XtMalloc(strlen(error) +
  681.                  strlen(app_res.save_prompt) + 2);
  682.         sprintf(buf, "%s\n%s", error, app_res.save_prompt);
  683.         SetDialogPrompt(dialog, buf);
  684.         XtFree(error);
  685.         XtFree(buf);
  686.     } else {
  687.         XtPopdown(XtParent(dialog));
  688.     }
  689.     break;
  690.     }
  691.     XtFree(name);
  692. }
  693.  
  694. /* Dismiss popup window */
  695. void
  696. dismiss(w, client_data, call_data)
  697.     Widget w;
  698.     XtPointer client_data, call_data;
  699. {
  700.     XtPopdown((Widget)client_data);
  701.     if ((Widget)client_data == infopopup) info_up = False;
  702. }
  703.  
  704. /* Destroy popup window */
  705. void
  706. destroy(w, client_data, call_data)
  707.     Widget w;
  708.     XtPointer client_data, call_data;
  709. {
  710.     XtDestroyWidget((Widget)client_data);
  711. }
  712.  
  713. /* destroy callback for Ghostview widgets. */
  714. /* The disable interpreter call ensures that ghostscript is killed. */
  715. /* One the count goes to 0, we are sure that all forked processes have */
  716. /* been killed and that we can safely exit. */
  717. void
  718. destroy_ghost(w, client_data, call_data)
  719.     Widget w;
  720.     XtPointer client_data, call_data;
  721. {
  722.     GhostviewDisableInterpreter((Widget) client_data);
  723.     num_ghosts--;
  724.     if (num_ghosts) return;
  725.     if (dying) old_Xerror(XtDisplay(w), &bomb);
  726.     XtDestroyApplicationContext(app_con);
  727.     exit(0);
  728. }
  729.